/*
//
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2008 Intel Corporation. All Rights Reserved.
//
//
*/

#include "umc_defs.h"
#if defined(UMC_ENABLE_AVS_VIDEO_ENCODER)

#include "umc_avs_enc_compressor.h"
#include "umc_avs_pic.h"

namespace UMC
{

static
IppiSize AVSLumaBlockSize[4] =
{
    {16, 16}, {16, 8}, {8, 16}, {8, 8}
};

static
IppiSize AVSChromaBlockSize[2][4] =
{
    // 4:2:0 block sizes
    {
        {8, 8}, {8, 4}, {4, 8}, {4, 4}
    },

    // 4:2:2 block sizes
    {
        {8, 16}, {8, 8}, {4, 16}, {4, 8}
    }
};

void AVSCompressor::CompensateMotionLumaPMacroBlock(Ipp8u *pDst, Ipp32s dstStep)
{
    // set pointer to the block's beginning
    //m_lumaMCParams.pDst[0] = m_recCtx.m_pPlanes8u[0];
    //m_lumaMCParams.dstStep = m_recCtx.m_iPitch;
    m_lumaMCParams.pDst[0] = pDst;
    m_lumaMCParams.dstStep = dstStep;

    // set the initial block position
    m_lumaMCParams.pointBlockPos.x = m_recCtx.MbX * 16;
    m_lumaMCParams.pointBlockPos.y = m_recCtx.MbY * 16;

    // select block size
    m_lumaMCParams.sizeBlock = AVSLumaBlockSize[m_pMbInfo->divType];

    switch (m_pMbInfo->divType)
    {
    case Div_16x16:
        CompensateMotionLumaUniDir(0, PredForward);
        break;

    case Div_16x8:
        CompensateMotionLumaUniDir(0, PredForward);

        m_lumaMCParams.pointBlockPos.y += 8;
        m_lumaMCParams.pDst[0] += m_lumaMCParams.dstStep * 8;
        CompensateMotionLumaUniDir(2, PredForward);
        break;

    case Div_8x16:
        CompensateMotionLumaUniDir(0, PredForward);

        m_lumaMCParams.pointBlockPos.x += 8;
        m_lumaMCParams.pDst[0] += 8;
        CompensateMotionLumaUniDir(1, PredForward);
        break;

    default:
        CompensateMotionLumaUniDir(0, PredForward);

        m_lumaMCParams.pointBlockPos.x += 8;
        m_lumaMCParams.pDst[0] += 8;
        CompensateMotionLumaUniDir(1, PredForward);

        m_lumaMCParams.pointBlockPos.x -= 8;
        m_lumaMCParams.pointBlockPos.y += 8;
        m_lumaMCParams.pDst[0] += m_lumaMCParams.dstStep * 8 - 8;
        CompensateMotionLumaUniDir(2, PredForward);

        m_lumaMCParams.pointBlockPos.x += 8;
        m_lumaMCParams.pDst[0] += 8;
        CompensateMotionLumaUniDir(3, PredForward);
        break;
    }

} // void AVSCompressor::CompensateMotionLumaPMacroBlock(Ipp8u *pDst, Ipp32s dstStep)

#define COMPENSATE_MOTION_LUMA(block_num) \
{ \
    eAVSPredType predType; \
    predType = (eAVSPredType) m_pMbInfo->predType[block_num]; \
    if (PredBiDir == predType) \
    { \
        CompensateMotionLumaBiDir(block_num); \
    } \
    else \
    { \
        CompensateMotionLumaUniDir(block_num, predType); \
    } \
}

void AVSCompressor::CompensateMotionLumaBMacroBlock(Ipp8u *pDst, Ipp32s dstStep)
{
    // set pointer to the block's beginning
    //m_lumaMCParams.pDst[0] = m_recCtx.m_pPlanes8u[0];
    //m_lumaMCParams.dstStep = m_recCtx.m_iPitch;
    m_lumaMCParams.pDst[0] = pDst;
    m_lumaMCParams.dstStep = dstStep;


    // set the initial block position
    m_lumaMCParams.pointBlockPos.x = m_recCtx.MbX * 16;
    m_lumaMCParams.pointBlockPos.y = m_recCtx.MbY * 16;

    // select block size
    m_lumaMCParams.sizeBlock = AVSLumaBlockSize[m_pMbInfo->divType];

    switch (m_pMbInfo->divType)
    {
    case Div_16x16:
        COMPENSATE_MOTION_LUMA(0)
        break;

    case Div_16x8:
        COMPENSATE_MOTION_LUMA(0)

        m_lumaMCParams.pointBlockPos.y += 8;
        m_lumaMCParams.pDst[0] += m_lumaMCParams.dstStep * 8;
        COMPENSATE_MOTION_LUMA(2)
        break;

    case Div_8x16:
        COMPENSATE_MOTION_LUMA(0)

        m_lumaMCParams.pointBlockPos.x += 8;
        m_lumaMCParams.pDst[0] += 8;
        COMPENSATE_MOTION_LUMA(1)
        break;

    default:
        COMPENSATE_MOTION_LUMA(0)

        m_lumaMCParams.pointBlockPos.x += 8;
        m_lumaMCParams.pDst[0] += 8;
        COMPENSATE_MOTION_LUMA(1)

        m_lumaMCParams.pointBlockPos.x -= 8;
        m_lumaMCParams.pointBlockPos.y += 8;
        m_lumaMCParams.pDst[0] += m_lumaMCParams.dstStep * 8 - 8;
        COMPENSATE_MOTION_LUMA(2)

        m_lumaMCParams.pointBlockPos.x += 8;
        m_lumaMCParams.pDst[0] += 8;
        COMPENSATE_MOTION_LUMA(3)
        break;
    }

} // void AVSCompressor::CompensateMotionLumaBMacroBlock(Ipp8u *pDst, Ipp32s dstStep)

void AVSCompressor::CompensateMotionLumaBiDir(Ipp32s blockNum)
{
    Ipp8u tempBlock[16 * 16 + 16];
    Ipp8u *pFrw, *pBck;
    Ipp32s stepFrw, stepBck;

    //
    // do forward motion compensation
    //

    // zero motion vector - simple reset pointers
    //if (0 == m_pMbInfo->mv[AVS_FORWARD][blockNum].scalar)
    //{
    //    Ipp32s refIdx;
    //    AVSPicture *pRef;

    //    refIdx = m_pMbInfo->refIdx[AVS_FORWARD][blockNum];
    //    pRef = m_pRefs[AVS_FORWARD][refIdx];
    //    pFrw = pRef->m_pPlanes8u[0];
    //    stepFrw = pRef->m_iPitch;

    //    // calculate offset to a corresponding place in the reference picture
    //    pFrw += m_lumaMCParams.pDst[0] - m_pPlanes8u[0];

    //    // do weighting
    //    if (m_pMbInfo->weighting_prediction)
    //    {
    //        Ipp32s luma_scale, luma_shift;

    //        // get weighting parameters
    //        luma_scale = m_recCtx.m_pSlcHeader->luma_scale[AVS_FORWARD][refIdx];
    //        luma_shift = m_recCtx.m_pSlcHeader->luma_shift[AVS_FORWARD][refIdx];

    //        ippiWeightPrediction_AVS_8u_C1R(pFrw,
    //                                        stepFrw,
    //                                        m_lumaMCParams.pDst[0],
    //                                        m_lumaMCParams.dstStep,
    //                                        luma_scale,
    //                                        luma_shift,
    //                                        m_lumaMCParams.sizeBlock);

    //        // set the pointer to the block
    //        pFrw = m_lumaMCParams.pDst[0];
    //        stepFrw = m_lumaMCParams.dstStep;
    //    }
    //}
    //// doing honest compensation
    //else
    {
        pFrw = m_lumaMCParams.pDst[0];
        stepFrw = m_lumaMCParams.dstStep;
        CompensateMotionLumaUniDir(blockNum, PredForward);
    }

    //
    // do backward motion compensation
    //

    // zero motion vector - simple reset pointers
    //if (0 == m_pMbInfo->mv[AVS_BACKWARD][blockNum].scalar)
    //{
    //    Ipp32s refIdx;
    //    AVSPicture *pRef;

    //    refIdx = m_pMbInfo->refIdx[AVS_BACKWARD][blockNum];
    //    pRef = m_pRefs[AVS_BACKWARD][refIdx];
    //    pBck = pRef->m_pPlanes8u[0];
    //    stepBck = pRef->m_iPitch;

    //    // calculate offset to a corresponding place in the reference picture
    //    pBck += m_lumaMCParams.pDst[0] - m_pPlanes8u[0];

    //    // do weighting
    //    if (m_pMbInfo->weighting_prediction)
    //    {
    //        Ipp32s luma_scale, luma_shift;

    //        // get weighting parameters
    //        luma_scale = m_recCtx.m_pSlcHeader->luma_scale[AVS_BACKWARD][refIdx];
    //        luma_shift = m_recCtx.m_pSlcHeader->luma_shift[AVS_BACKWARD][refIdx];

    //        ippiWeightPrediction_AVS_8u_C1R(pBck,
    //                                        stepBck,
    //                                        align_pointer<Ipp8u *> (tempBlock, 16),
    //                                        16,
    //                                        luma_scale,
    //                                        luma_shift,
    //                                        m_lumaMCParams.sizeBlock);

    //        // set the pointer to the block
    //        pBck = align_pointer<Ipp8u *> (tempBlock, 16);
    //        stepBck = 16;
    //    }
    //}
    //// doing honest compensation
    //else
    {
        Ipp8u *pDstPrev;
        Ipp32s stepPrev;

        // change the destination pointer
        pDstPrev = m_lumaMCParams.pDst[0];
        stepPrev = m_lumaMCParams.dstStep;
        m_lumaMCParams.pDst[0] = align_pointer<Ipp8u *> (tempBlock, 16);
        m_lumaMCParams.dstStep = 16;

        pBck = m_lumaMCParams.pDst[0];
        stepBck = m_lumaMCParams.dstStep;
        CompensateMotionLumaUniDir(blockNum, PredBackward);

        // restore the destination pointer
        m_lumaMCParams.pDst[0] = pDstPrev;
        m_lumaMCParams.dstStep = stepPrev;
    }

    // get average from two directions
    ippiInterpolateBlock_H264_8u_P3P1R(pFrw,
                                       pBck,
                                       m_lumaMCParams.pDst[0],
                                       m_lumaMCParams.sizeBlock.width,
                                       m_lumaMCParams.sizeBlock.height,
                                       stepFrw,
                                       stepBck,
                                       m_lumaMCParams.dstStep);


} // void AVSCompressor::CompensateMotionLumaBiDir(Ipp32s blockNum)


//void AVSDecompressor::CompensateMotionLumaUniDir(Ipp32s blockNum, eAVSPredType typePred)
//{
//    Ipp32s refIdx;
//
//    // set the source
//    {
//        AVSPicture *pRef;
//
//        refIdx = m_pMbInfo->refIdx[typePred - 1][blockNum];
//        pRef = m_pRefs[typePred - 1][refIdx];
//        m_lumaMCParams.pSrc[0] = pRef->m_pPlanes8u[0];
//        m_lumaMCParams.srcStep = pRef->m_iPitch;
//    }
//
//    // set the vector
//    m_lumaMCParams.pointVector = m_pMbInfo->mv[typePred - 1][blockNum];
//
//    // do compensation
//    ippiInterpolateLumaBlock_AVS_8u_P1R(&m_lumaMCParams);
//
//    // do weighting
//    if (m_pMbInfo->weighting_prediction)
//    {
//        Ipp32s luma_scale, luma_shift;
//
//        // get weighting parameters
//        luma_scale = m_recCtx.m_pSlcHeader->luma_scale[typePred - 1][refIdx];
//        luma_shift = m_recCtx.m_pSlcHeader->luma_shift[typePred - 1][refIdx];
//
//        ippiWeightPrediction_AVS_8u_C1R(m_lumaMCParams.pDst[0],
//                                        m_lumaMCParams.dstStep,
//                                        m_lumaMCParams.pDst[0],
//                                        m_lumaMCParams.dstStep,
//                                        luma_scale,
//                                        luma_shift,
//                                        m_lumaMCParams.sizeBlock);
//    }
//
//} // void AVSDecompressor::CompensateMotionLumaUniDir(Ipp32s blockNum, eAVSPredType typePred)
//
//void AVSDecompressor::CompensateMotionLumaBiDir(Ipp32s blockNum)
//{
//    Ipp8u tempBlock[16 * 16 + 16];
//    Ipp8u *pFrw, *pBck;
//    Ipp32s stepFrw, stepBck;
//
//    //
//    // do forward motion compensation
//    //
//
//    // zero motion vector - simple reset pointers
//    if (0 == m_pMbInfo->mv[AVS_FORWARD][blockNum].scalar)
//    {
//        Ipp32s refIdx;
//        AVSPicture *pRef;
//
//        refIdx = m_pMbInfo->refIdx[AVS_FORWARD][blockNum];
//        pRef = m_pRefs[AVS_FORWARD][refIdx];
//        pFrw = pRef->m_pPlanes8u[0];
//        stepFrw = pRef->m_iPitch;
//
//        // calculate offset to a corresponding place in the reference picture
//        pFrw += m_lumaMCParams.pDst[0] - m_pPlanes8u[0];
//
//        // do weighting
//        if (m_pMbInfo->weighting_prediction)
//        {
//            Ipp32s luma_scale, luma_shift;
//
//            // get weighting parameters
//            luma_scale = m_recCtx.m_pSlcHeader->luma_scale[AVS_FORWARD][refIdx];
//            luma_shift = m_recCtx.m_pSlcHeader->luma_shift[AVS_FORWARD][refIdx];
//
//            ippiWeightPrediction_AVS_8u_C1R(pFrw,
//                                            stepFrw,
//                                            m_lumaMCParams.pDst[0],
//                                            m_lumaMCParams.dstStep,
//                                            luma_scale,
//                                            luma_shift,
//                                            m_lumaMCParams.sizeBlock);
//
//            // set the pointer to the block
//            pFrw = m_lumaMCParams.pDst[0];
//            stepFrw = m_lumaMCParams.dstStep;
//        }
//    }
//    // doing honest compensation
//    else
//    {
//        pFrw = m_lumaMCParams.pDst[0];
//        stepFrw = m_lumaMCParams.dstStep;
//        CompensateMotionLumaUniDir(blockNum, PredForward);
//    }
//
//    //
//    // do backward motion compensation
//    //
//
//    // zero motion vector - simple reset pointers
//    if (0 == m_pMbInfo->mv[AVS_BACKWARD][blockNum].scalar)
//    {
//        Ipp32s refIdx;
//        AVSPicture *pRef;
//
//        refIdx = m_pMbInfo->refIdx[AVS_BACKWARD][blockNum];
//        pRef = m_pRefs[AVS_BACKWARD][refIdx];
//        pBck = pRef->m_pPlanes8u[0];
//        stepBck = pRef->m_iPitch;
//
//        // calculate offset to a corresponding place in the reference picture
//        pBck += m_lumaMCParams.pDst[0] - m_pPlanes8u[0];
//
//        // do weighting
//        if (m_pMbInfo->weighting_prediction)
//        {
//            Ipp32s luma_scale, luma_shift;
//
//            // get weighting parameters
//            luma_scale = m_recCtx.m_pSlcHeader->luma_scale[AVS_BACKWARD][refIdx];
//            luma_shift = m_recCtx.m_pSlcHeader->luma_shift[AVS_BACKWARD][refIdx];
//
//            ippiWeightPrediction_AVS_8u_C1R(pBck,
//                                            stepBck,
//                                            align_pointer<Ipp8u *> (tempBlock, 16),
//                                            16,
//                                            luma_scale,
//                                            luma_shift,
//                                            m_lumaMCParams.sizeBlock);
//
//            // set the pointer to the block
//            pBck = align_pointer<Ipp8u *> (tempBlock, 16);
//            stepBck = 16;
//        }
//    }
//    // doing honest compensation
//    else
//    {
//        Ipp8u *pDstPrev;
//        Ipp32s stepPrev;
//
//        // change the destination pointer
//        pDstPrev = m_lumaMCParams.pDst[0];
//        stepPrev = m_lumaMCParams.dstStep;
//        m_lumaMCParams.pDst[0] = align_pointer<Ipp8u *> (tempBlock, 16);
//        m_lumaMCParams.dstStep = 16;
//
//        pBck = m_lumaMCParams.pDst[0];
//        stepBck = m_lumaMCParams.dstStep;
//        CompensateMotionLumaUniDir(blockNum, PredBackward);
//
//        // restore the destination pointer
//        m_lumaMCParams.pDst[0] = pDstPrev;
//        m_lumaMCParams.dstStep = stepPrev;
//    }
//
//    // get average from two directions
//    ippiInterpolateBlock_H264_8u_P3P1R(pFrw,
//                                       pBck,
//                                       m_lumaMCParams.pDst[0],
//                                       m_lumaMCParams.sizeBlock.width,
//                                       m_lumaMCParams.sizeBlock.height,
//                                       stepFrw,
//                                       stepBck,
//                                       m_lumaMCParams.dstStep);
//
//
//} // void AVSDecompressor::CompensateMotionLumaBiDir(Ipp32s blockNum)
//

void AVSCompressor::CompensateMotionChromaPMacroBlock(Ipp8u *pDstU, Ipp8u *pDstV, Ipp32s dstStep)
{
    Ipp32s blockHeight;

    // set pointer to the block's beginning
    //m_chromaMCParams.pDst[0] = m_recCtx.m_pPlanes8u[1];
    //m_chromaMCParams.pDst[1] = m_recCtx.m_pPlanes8u[2];
    //m_chromaMCParams.dstStep = m_recCtx.m_iPitch;

    m_chromaMCParams.pDst[0] = pDstU;
    m_chromaMCParams.pDst[1] = pDstV;
    m_chromaMCParams.dstStep = dstStep;

    // set the initial block position
    m_chromaMCParams.pointBlockPos.x = m_recCtx.MbX * 8;
    m_chromaMCParams.pointBlockPos.y = m_recCtx.MbY * 8;

    // select block size
    m_chromaMCParams.sizeBlock = AVSChromaBlockSize[m_recCtx.m_pSeqHeader->chroma_format - 1]
                                                   [m_pMbInfo->divType];
    blockHeight = m_chromaMCParams.sizeBlock.height;

    switch (m_pMbInfo->divType)
    {
    case Div_16x16:
        CompensateMotionChromaUniDir(0, PredForward);
        break;

    case Div_16x8:
        CompensateMotionChromaUniDir(0, PredForward);

        m_chromaMCParams.pointBlockPos.y += blockHeight;
        m_chromaMCParams.pDst[0] += m_chromaMCParams.dstStep * blockHeight;
        m_chromaMCParams.pDst[1] += m_chromaMCParams.dstStep * blockHeight;
        CompensateMotionChromaUniDir(2, PredForward);
        break;

    case Div_8x16:
        CompensateMotionChromaUniDir(0, PredForward);

        m_chromaMCParams.pointBlockPos.x += 4;
        m_chromaMCParams.pDst[0] += 4;
        m_chromaMCParams.pDst[1] += 4;
        CompensateMotionChromaUniDir(1, PredForward);
        break;

    default:
        CompensateMotionChromaUniDir(0, PredForward);

        m_chromaMCParams.pointBlockPos.x += 4;
        m_chromaMCParams.pDst[0] += 4;
        m_chromaMCParams.pDst[1] += 4;
        CompensateMotionChromaUniDir(1, PredForward);

        m_chromaMCParams.pointBlockPos.x -= 4;
        m_chromaMCParams.pointBlockPos.y += blockHeight;
        m_chromaMCParams.pDst[0] += m_chromaMCParams.dstStep * blockHeight - 4;
        m_chromaMCParams.pDst[1] += m_chromaMCParams.dstStep * blockHeight - 4;
        CompensateMotionChromaUniDir(2, PredForward);

        m_chromaMCParams.pointBlockPos.x += 4;
        m_chromaMCParams.pDst[0] += 4;
        m_chromaMCParams.pDst[1] += 4;
        CompensateMotionChromaUniDir(3, PredForward);
        break;
    }

} // void AVSCompressor::CompensateMotionChromaPMacroBlock(Ipp8u *pDst[2], Ipp32s dstStep)

#define COMPENSATE_MOTION_CHROMA(block_num) \
{ \
    eAVSPredType predType; \
    predType = (eAVSPredType) m_pMbInfo->predType[block_num]; \
    if (PredBiDir == predType) \
    { \
        CompensateMotionChromaBiDir(block_num); \
    } \
    else \
    { \
        CompensateMotionChromaUniDir(block_num, predType); \
    } \
}

void AVSCompressor::CompensateMotionChromaBMacroBlock(Ipp8u *pDstU, Ipp8u *pDstV, Ipp32s dstStep)
{
    Ipp32s blockHeight;

    // set pointer to the block's beginning
    //m_chromaMCParams.pDst[0] = m_recCtx.m_pPlanes8u[1];
    //m_chromaMCParams.pDst[1] = m_recCtx.m_pPlanes8u[2];
    //m_chromaMCParams.dstStep = m_recCtx.m_iPitch;

    m_chromaMCParams.pDst[0] = pDstU;
    m_chromaMCParams.pDst[1] = pDstV;
    m_chromaMCParams.dstStep = dstStep;

    // set the initial block position
    m_chromaMCParams.pointBlockPos.x = m_recCtx.MbX * 8;
    m_chromaMCParams.pointBlockPos.y = m_recCtx.MbY * 8;

    // select block size
    m_chromaMCParams.sizeBlock = AVSChromaBlockSize[m_recCtx.m_pSeqHeader->chroma_format - 1]
                                                   [m_pMbInfo->divType];
    blockHeight = m_chromaMCParams.sizeBlock.height;

    switch (m_pMbInfo->divType)
    {
    case Div_16x16:
        COMPENSATE_MOTION_CHROMA(0);
        break;

    case Div_16x8:
        COMPENSATE_MOTION_CHROMA(0);

        m_chromaMCParams.pointBlockPos.y += blockHeight;
        m_chromaMCParams.pDst[0] += m_chromaMCParams.dstStep * blockHeight;
        m_chromaMCParams.pDst[1] += m_chromaMCParams.dstStep * blockHeight;
        COMPENSATE_MOTION_CHROMA(2);
        break;

    case Div_8x16:
        COMPENSATE_MOTION_CHROMA(0);

        m_chromaMCParams.pointBlockPos.x += 4;
        m_chromaMCParams.pDst[0] += 4;
        m_chromaMCParams.pDst[1] += 4;
        COMPENSATE_MOTION_CHROMA(1);
        break;

    default:
        COMPENSATE_MOTION_CHROMA(0);

        m_chromaMCParams.pointBlockPos.x += 4;
        m_chromaMCParams.pDst[0] += 4;
        m_chromaMCParams.pDst[1] += 4;
        COMPENSATE_MOTION_CHROMA(1);

        m_chromaMCParams.pointBlockPos.x -= 4;
        m_chromaMCParams.pointBlockPos.y += blockHeight;
        m_chromaMCParams.pDst[0] += m_chromaMCParams.dstStep * blockHeight - 4;
        m_chromaMCParams.pDst[1] += m_chromaMCParams.dstStep * blockHeight - 4;
        COMPENSATE_MOTION_CHROMA(2);

        m_chromaMCParams.pointBlockPos.x += 4;
        m_chromaMCParams.pDst[0] += 4;
        m_chromaMCParams.pDst[1] += 4;
        COMPENSATE_MOTION_CHROMA(3);
        break;
    }

} // void AVSDecompressor::CompensateMotionChromaBMacroBlock(Ipp8u *pDst[2], Ipp32s dstStep)

//#define ippiInterpolateChromaBlock_AVS_8u_P2R \
//    ippiInterpolateChromaBlock_H264_8u_P2R

//void AVSDecompressor::CompensateMotionChromaUniDir(Ipp32s blockNum, eAVSPredType typePred)
//{
//    Ipp32s refIdx;
//
//    // set the source
//    {
//        AVSPicture *pRef;
//
//        refIdx = m_pMbInfo->refIdx[typePred - 1][blockNum];
//        pRef = m_pRefs[typePred - 1][refIdx];
//        m_chromaMCParams.pSrc[0] = pRef->m_pPlanes8u[1];
//        m_chromaMCParams.pSrc[1] = pRef->m_pPlanes8u[2];
//        m_chromaMCParams.srcStep = pRef->m_iPitch;
//    }
//
//    // set the vector
//    m_chromaMCParams.pointVector = m_pMbInfo->mv[typePred - 1][blockNum];
//
//    // do compensation
//    ippiInterpolateChromaBlock_AVS_8u_P2R(&m_chromaMCParams);
//
//    // do weighting
//    if (m_pMbInfo->weighting_prediction)
//    {
//        Ipp32s chroma_scale, chroma_shift;
//
//        // get weighting parameters
//        chroma_scale = m_recCtx.m_pSlcHeader->chroma_scale[typePred - 1][refIdx];
//        chroma_shift = m_recCtx.m_pSlcHeader->chroma_shift[typePred - 1][refIdx];
//
//        ippiWeightPrediction_AVS_8u_C1R(m_chromaMCParams.pDst[0],
//                                        m_chromaMCParams.dstStep,
//                                        m_chromaMCParams.pDst[0],
//                                        m_chromaMCParams.dstStep,
//                                        chroma_scale,
//                                        chroma_shift,
//                                        m_chromaMCParams.sizeBlock);
//        ippiWeightPrediction_AVS_8u_C1R(m_chromaMCParams.pDst[1],
//                                        m_chromaMCParams.dstStep,
//                                        m_chromaMCParams.pDst[1],
//                                        m_chromaMCParams.dstStep,
//                                        chroma_scale,
//                                        chroma_shift,
//                                        m_chromaMCParams.sizeBlock);
//    }
//
//} // void AVSDecompressor::CompensateMotionChromaUniDir(Ipp32s blockNum, eAVSPredType typePred)
//
void AVSCompressor::CompensateMotionChromaBiDir(Ipp32s blockNum)
{
    Ipp8u tempBlock[16 * 16 + 16];
    Ipp8u *(pFrw[2]), *(pBck[2]);
    Ipp32s stepFrw, stepBck;

    //
    // do forward motion compensation
    //

    // zero motion vector - simple reset pointers
    //if (0 == m_pMbInfo->mv[AVS_FORWARD][blockNum].scalar)
    //{
    //    Ipp32s refIdx;
    //    AVSPicture *pRef;

    //    refIdx = m_pMbInfo->refIdx[AVS_FORWARD][blockNum];
    //    pRef = m_pRefs[AVS_FORWARD][refIdx];
    //    pFrw[0] = pRef->m_pPlanes8u[1];
    //    pFrw[1] = pRef->m_pPlanes8u[2];
    //    stepFrw = pRef->m_iPitch;

    //    // calculate offset to a corresponding place in the reference picture
    //    pFrw[0] += m_chromaMCParams.pDst[0] - m_pPlanes8u[1];
    //    pFrw[1] += m_chromaMCParams.pDst[1] - m_pPlanes8u[2];

    //    // do weighting
    //    if (m_pMbInfo->weighting_prediction)
    //    {
    //        Ipp32s chroma_scale, chroma_shift;

    //        // get weighting parameters
    //        chroma_scale = m_recCtx.m_pSlcHeader->chroma_scale[AVS_FORWARD][refIdx];
    //        chroma_shift = m_recCtx.m_pSlcHeader->chroma_shift[AVS_FORWARD][refIdx];

    //        ippiWeightPrediction_AVS_8u_C1R(pFrw[0],
    //                                        stepFrw,
    //                                        m_chromaMCParams.pDst[0],
    //                                        m_chromaMCParams.dstStep,
    //                                        chroma_scale,
    //                                        chroma_shift,
    //                                        m_chromaMCParams.sizeBlock);
    //        ippiWeightPrediction_AVS_8u_C1R(pFrw[1],
    //                                        stepFrw,
    //                                        m_chromaMCParams.pDst[1],
    //                                        m_chromaMCParams.dstStep,
    //                                        chroma_scale,
    //                                        chroma_shift,
    //                                        m_chromaMCParams.sizeBlock);

    //        // set the pointers to the blocks
    //        pFrw[0] = m_chromaMCParams.pDst[0];
    //        pFrw[1] = m_chromaMCParams.pDst[1];
    //        stepFrw = m_chromaMCParams.dstStep;
    //    }
    //}
    //// doing honest compensation
    //else
    {
        pFrw[0] = m_chromaMCParams.pDst[0];
        pFrw[1] = m_chromaMCParams.pDst[1];
        stepFrw = m_chromaMCParams.dstStep;
        CompensateMotionChromaUniDir(blockNum, PredForward);
    }

    //
    // do backward motion compensation
    //

    //// zero motion vector - simple reset pointers
    //if (0 == m_pMbInfo->mv[AVS_BACKWARD][blockNum].scalar)
    //{
    //    Ipp32s refIdx;
    //    AVSPicture *pRef;

    //    refIdx = m_pMbInfo->refIdx[AVS_BACKWARD][blockNum];
    //    pRef = m_pRefs[AVS_BACKWARD][refIdx];
    //    pBck[0] = pRef->m_pPlanes8u[1];
    //    pBck[1] = pRef->m_pPlanes8u[2];
    //    stepBck = pRef->m_iPitch;

    //    // calculate offset to a corresponding place in the reference picture
    //    pBck[0] += m_chromaMCParams.pDst[0] - m_pPlanes8u[1];
    //    pBck[1] += m_chromaMCParams.pDst[1] - m_pPlanes8u[2];

    //    // do weighting
    //    if (m_pMbInfo->weighting_prediction)
    //    {
    //        Ipp32s chroma_scale, chroma_shift;

    //        // get weighting parameters
    //        chroma_scale = m_recCtx.m_pSlcHeader->chroma_scale[AVS_BACKWARD][refIdx];
    //        chroma_shift = m_recCtx.m_pSlcHeader->chroma_shift[AVS_BACKWARD][refIdx];

    //        ippiWeightPrediction_AVS_8u_C1R(pBck[0],
    //                                        stepBck,
    //                                        align_pointer<Ipp8u *> (tempBlock, 16),
    //                                        16,
    //                                        chroma_scale,
    //                                        chroma_shift,
    //                                        m_chromaMCParams.sizeBlock);
    //        ippiWeightPrediction_AVS_8u_C1R(pBck[1],
    //                                        stepBck,
    //                                        align_pointer<Ipp8u *> (tempBlock, 16) + 8,
    //                                        16,
    //                                        chroma_scale,
    //                                        chroma_shift,
    //                                        m_chromaMCParams.sizeBlock);

    //        // set the pointers to the blocks
    //        pBck[0] = align_pointer<Ipp8u *> (tempBlock, 16);
    //        pBck[1] = align_pointer<Ipp8u *> (tempBlock, 16) + 8;
    //        stepBck = 16;
    //    }
    //}
    //// doing honest compensation
    //else
    {
        Ipp8u *(pDstPrev[2]);
        Ipp32s stepPrev;

        // change the destination pointer
        pDstPrev[0] = m_chromaMCParams.pDst[0];
        pDstPrev[1] = m_chromaMCParams.pDst[1];
        stepPrev = m_chromaMCParams.dstStep;
        m_chromaMCParams.pDst[0] = align_pointer<Ipp8u *> (tempBlock, 16);
        m_chromaMCParams.pDst[1] = align_pointer<Ipp8u *> (tempBlock, 16) + 8;
        m_chromaMCParams.dstStep = 16;

        pBck[0] = m_chromaMCParams.pDst[0];
        pBck[1] = m_chromaMCParams.pDst[1];
        stepBck = m_chromaMCParams.dstStep;
        CompensateMotionChromaUniDir(blockNum, PredBackward);

        // restore the destination pointer
        m_chromaMCParams.pDst[0] = pDstPrev[0];
        m_chromaMCParams.pDst[1] = pDstPrev[1];
        m_chromaMCParams.dstStep = stepPrev;
    }

    // get average from two directions
    ippiInterpolateBlock_H264_8u_P3P1R(pFrw[0],
                                       pBck[0],
                                       m_chromaMCParams.pDst[0],
                                       m_chromaMCParams.sizeBlock.width,
                                       m_chromaMCParams.sizeBlock.height,
                                       stepFrw,
                                       stepBck,
                                       m_chromaMCParams.dstStep);
    ippiInterpolateBlock_H264_8u_P3P1R(pFrw[1],
                                       pBck[1],
                                       m_chromaMCParams.pDst[1],
                                       m_chromaMCParams.sizeBlock.width,
                                       m_chromaMCParams.sizeBlock.height,
                                       stepFrw,
                                       stepBck,
                                       m_chromaMCParams.dstStep);


} // void AVSCompressor::CompensateMotionChromaBiDir(Ipp32s blockNum)

} // namespace UMC

#endif // defined(UMC_ENABLE_AVS_VIDEO_DECODER)
